package com.example.websocket.client;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.nio.ByteBuffer;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class SysWebSocketClient extends WebSocketClient {

    Logger logger = LoggerFactory.getLogger(getClass());

    private Long serverId;

    private String serverIp;

    private int serverPort;

    private int initialDelay = 20;

    private int period = 10;

    private int coreSize = 10;

    private WebSocketClientListener webSocketClientListener = new WebSocketClientListener() {
        @Override
        public void onOpen(ServerHandshake serverHandshake) {
            WebSocketClientListener.super.onOpen(serverHandshake);
        }

        @Override
        public void onClose(int code, String reason, boolean remote) {
            WebSocketClientListener.super.onClose(code, reason, remote);
        }

        @Override
        public void onError(Exception ex) {
            WebSocketClientListener.super.onError(ex);
        }

        @Override
        public void onMessage(String message) {
            WebSocketClientListener.super.onMessage(message);
        }

        @Override
        public void onMessage(ByteBuffer byteBuffer) {
            WebSocketClientListener.super.onMessage(byteBuffer);
        }
    };

    private ScheduledExecutorService scheduledExecutorService;

    public SysWebSocketClient(String serverIp, int serverPort, Long serverId, WebSocketClientListener webSocketClientListener) throws Exception {
        super(new URI("ws://" + serverIp + ":" + serverPort + "/" + serverId));
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        this.serverId = serverId;
        this.webSocketClientListener = webSocketClientListener;
        this.scheduledExecutorService = new ScheduledThreadPoolExecutor(coreSize);
    }

    public SysWebSocketClient(String serverIp, int serverPort, Long serverId) throws Exception {
        super(new URI("ws://" + serverIp + ":" + serverPort + "/" + serverId));
        this.serverIp = serverIp;
        this.serverPort = serverPort;
        this.serverId = serverId;
        this.scheduledExecutorService = new ScheduledThreadPoolExecutor(coreSize);
    }

    @Override
    public void onOpen(ServerHandshake serverHandshake) {
        logger.warn("connect server " + this.serverIp + ":" + this.serverPort + " success ...");
        webSocketClientListener.onOpen(serverHandshake);
    }

    @Override
    public void onMessage(String message) {
        logger.warn("receive string message from server " + this.serverIp + ":" + this.serverPort + " " + message);
        webSocketClientListener.onMessage(message);
    }

    @Override
    public void onMessage(ByteBuffer byteBuffer) {
        webSocketClientListener.onMessage(byteBuffer);
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        webSocketClientListener.onClose(code, reason, remote);
    }

    @Override
    public void onError(Exception ex) {
        webSocketClientListener.onError(ex);
    }

    public void start() {
        this.connect();
        this.scheduledExecutorService.scheduleAtFixedRate(new WebSocketClientConnectThread(), initialDelay, period, TimeUnit.SECONDS);
        logger.warn("client serverId " + this.serverId + " starting ...");
    }

    public void stop() {
        this.close();
        this.scheduledExecutorService.shutdown();
    }

    class WebSocketClientConnectThread implements Runnable {
        @Override
        public void run() {
            if (!isOpen()) {
                try {
                    reconnectBlocking();
                } catch (Exception e) {
                    logger.info("connect server " + serverIp + ":" + serverPort + " error " + e.getMessage());
                }
                logger.info("connect server " + serverIp + ":" + serverPort + " failed ，starting reconnect ...");
            }
        }
    }

    public interface WebSocketClientListener {

        default public void onOpen(ServerHandshake serverHandshake) {

        }

        default public void onClose(int code, String reason, boolean remote) {

        }

        default public void onError(Exception ex) {

        }

        default public void onMessage(String message) {

        }

        default public void onMessage(ByteBuffer byteBuffer) {

        }
    }
}
